<?php
defined('TD_TRUE')or die(header('HTTP/1.1 404 NOT FOUND'));
/**
 * 读模板页进行替换后写入到cache页里
 *
 * @param string $tplfile ：模板文件名
 * @param string $objfile ：cache文件名
 * @return
 */

class Template {
  var $template = '';
  var $subtemplates = array();
  var $lsta = '{';
  var $rsta = '}';
  var $lvar = '[';
  var $rvar = ']';

  //变量
  var $var_regexp = '([a-zA-Z_\?\x7f-\xff][a-zA-Z0-9\?_\x7f-\xff]*(\.[a-zA-Z0-9_\?\x7f-\xff]+)*)';
  //字符串
  var $str_regexp = '([\'\"]+(.*?)[\'\"]+)';
  //数字
  var $num_regexp = '([\-\+]?\d+(\.\d+)?)';
  //常量
  var $const_regexp = '([a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*)';

  var $tplrelativeuri = '';
  var $tplpath = '';
  var $tplfile = '';
  var $objpath = '';
  var $objfile = '';
  var $cate = '';
  var $tpl = '';
  var $tagindex = 0;
  var $varfuns = array('date_format' => 'dateformat', 'number_format' =>
    'number_format', 'escape' => 'escape', 'lower' => 'strtolower', 'replace'
    => 'str_replace', 'strip' => 'strip', 'strip_html' => 'strip_tags',
    'substr' => 'cutstr', 'upper' => 'strtoupper', 'count' => 'countarr','tostring'=>'tostring'
  );

  var $vartype = array('s' => '$_SYSVAR', 'u' => '$_USERVAR', 'l' => '$_L', 'v' => '$_PAGEVAR', 'g' => '$_GET','p' => '$_POST','c' => '$_COOKIE' );
  var $tables = array('article','album','category','comment','link','linkgroup','navigation','page','pic','tag','user');

  function Template($tpl, $type, $cate) {
    __construct($tpl, $type, $cate);
  }
  function __construct($tpl, $type, $cate) {
    //初始化
    global $_C;
    $this->tplrelativeuri = $_C['siterelativeurl'].'/views/'.$cate.'/'.$type.'/'.$_C[$cate][$type].'/';
    $this->tplpath = TD_ROOT.'./views/'.$cate.'/'.$type.'/'.$_C[$cate][$type].'/';
    $this->tplfile = $this->tplpath.$tpl.$_C['tpl_ex'];
    $this->objpath = TD_ROOT.'./cache/'.$cate.'/'.$type.'/'.$_C[$cate][$type].'/';
    $this->objfile = $this->objpath.$tpl.'.php';
    $this->subtemplates = array($tpl);
    $this->cate = $cate;
    $this->tpl = $tpl;
    if (!$this->tplfile || !$this->objfile) {
      exit("Template file : the tplfile and objfile should not be empty!");
    }
    if (function_exists('file_get_contents')) {
      @$this->template = file_get_contents($this->tplfile);
    } else {
      if (@$fp = fopen($this->tplfile, 'r')) {
        @$this->template = fread($fp, filesize($this->tplfile));
        @fclose($fp);
      }
    }
    if (empty($this->template)) {
      exit("Template file : $this->tplfile not found or have no access!");
    }
  }

  function parse() {
  	global $_G;
    $template = $this->template;
  //preg_quote
  $lsta = preg_quote($this->lsta);
  $rsta = preg_quote($this->rsta);
  $lvar = preg_quote($this->lvar);
  $rvar = preg_quote($this->rvar);
    $var_regexp = $this->var_regexp;
    $str_regexp = $this->str_regexp;
    $num_regexp = $this->num_regexp;
    $const_regexp = $this->const_regexp;
  //变量约束函数
  $var_modifier_regexp = '(((\|\s*('.implode('|',array_keys($this->varfuns)).'|\?))(.*?))*)';
    //开始处理,禁用PHP的支持
    /*$template = str_replace('<?', '{LTAG}', $template);
    $template = str_replace('?>', '{RTAG}', $template);
    $template = str_replace('<%', '{ASPLTAG}', $template);
    $template = str_replace('%>', '{ASPRTAG}', $template);
    $template = str_replace('{LTAG}','<?php echo \'<?\'; ?>', $template);
    $template = str_replace('{RTAG}','<?php echo \'?>\';?>', $template);
    $template = str_replace('{ASPLTAG}','<?php echo \'<%\'; ?>', $template);
    $template = str_replace('{ASPRTAG}','<?php echo \'%>\'; ?>', $template);
*/
    //pre标签 预存保留原格式的代码
    preg_match_all("/(<!--\s*)?".$lsta."pre".$rsta."(\s*-->)?(.*?)(<!--\s*)?".$lsta."\/pre".$rsta."(\s*-->)?/is", $template, $pre_old);
    //将pre标签内的内容替依次换为形如1、2、3等的形式的数字序列，使得pre标签内的内容不会参与模板解析，提高效率。
    $pre_new[0] = $pre_old[0];
    $prei = 0;
    foreach($pre_new[0] as &$v){
    	++$prei;
      $v = $this->lsta.'pre'.$this->rsta.$prei.$this->lsta.'/pre'.$this->rsta;
    	}
    $template = str_replace($pre_old[0], $pre_new[0],$template);

    //模板调用
    $template = preg_replace("/(<!--\s*)?".$lsta."\s*include\s+([a-z0-9_\/]+)\s*".$rsta."(\s*-->)?/ie", "Template::readtemplate('\\2','$this->tpl')", $template);

    //开始处理
    //注释
    $template = preg_replace("/(<!--\s*)?".$lsta."\*(.*?)\*".$rsta."(\s*-->)?/is", '', $template);
    //头像处理
     $template = preg_replace_callback("/_AVATAR_\s*\/\s*(\_)?(BIG|MEDIUM|SMALL)(_(".$lvar."\s*[a-zA-Z0-9_\x7f-\xff.]+\s*".$rvar."|\d+))?\.(GIF|PNG|JPG|BMP)/s", array( Template, 'tag_avatar'), $template);

    //设置用户自定义变量设置语句{set varname="value"}, 调用时[v:varname]其中v:可省略，所以[v:varname]和[varname]是等价的。
    $template = preg_replace_callback("/(<!--\s*)?".$lsta."\s*set\s+(".$lvar."\s*(([lLvVgGpPcC\?])\s*\:)?\s*".$var_regexp."\s*".$rvar."\s*\=\s*(.*?))\s*".$rsta."(\s*-->)?/is", array( Template, 'tag_set'), $template);
    //系统变量s,系统语言变量l,用户定义的全局变量u,页面局部变量v
    $template = preg_replace_callback("/(<!--\s*)?".$lvar."\s*(([sSuUlLvVgGpPcC\?])\s*\:)?\s*".$var_regexp.$var_modifier_regexp."\s*".$rvar."(\s*-->)?/s", array( Template, 'tag_var_out'), $template);
    //逻辑if语句
    $template = preg_replace("/(<!--\s*)?".$lsta."\s*if\s+(.+?)\s*".$rsta."(\s*-->)?/ies", "Template::stripvtags('<?php if(\\2) { ?>','')", $template);
    $template = preg_replace("/(<!--\s*)?".$lsta."\s*\/if\s*".$rsta."(\s*-->)?/is", "<?php } ?>", $template);
    $template = preg_replace("/(<!--\s*)?".$lsta."\s*elseif\s+(.+?)\s*".$rsta."(\s*-->)?/ies", "Template::stripvtags('<?php } elseif(\\2) { ?>'')", $template);
    $template = preg_replace("/(<!--\s*)?".$lsta."\s*else\s*".$rsta."(\s*-->)?/is", "<?php } else { ?>", $template);
    //循环 loop 语句
    $template = preg_replace_callback("/(<!--\s*)?".$lsta."\s*loop\s+(.+?)\s+in\s+(.+?)\s*".$rsta."(\s*-->)?/is",  array( Template, 'tag_loop'), $template);
    $template = preg_replace("/(<!--\s*)?".$lsta."\s*\/loop\s*".$rsta."(\s*-->)?/is", "<?php } } ?>", $template);
    //block
    $template = preg_replace_callback("/(<!--\s*)?".$lsta."\s*block\s*\:\s*([a-zA-Z_][a-zA-Z0-9_]*|\?)((\s+([a-zA-Z0-9_]+\s*\=\s*([\d\.]+|\"\s*.*?\s*\")))*)\s*".$rsta."(\s*-->)?/is",  array( Template, 'tag_block'), $template);
    //item
    $template = preg_replace_callback("/(<!--\s*)?".$lsta."\s*item\s*\:\s*([a-zA-Z_][a-zA-Z0-9_]*|\?)((\s+([a-zA-Z0-9_]+\s*\=\s*([\d\.]+|\"\s*.*?\s*\")))*)\s*".$rsta."(\s*-->)?/is",  array( Template, 'tag_item'), $template);
    //url_wrap
    /*$template = preg_replace_callback("/(<!--\s*)?".$lsta."\s*url\s*\:\s*([a-zA-Z0-9_]+(\,[a-zA-Z0-9_]*)*)\s*".$rsta."(\s*-->)?/is", array( Template, 'tag_url'), $template);*/
     $template = preg_replace_callback("/(<!--\s*)?".$lsta."\s*url\s*\:\s*((.+?)(\,(.*?))*)\s*".$rsta."(\s*-->)?/is", array( Template, 'tag_url'), $template);
    //模板特殊变量的支持
    $template = str_replace('_TPL_', $this->tplrelativeuri.'_TPL_' , $template);
    //clear语句
    $template = preg_replace("/(<!--\s*)?".$lsta."\s*(clear)\s*".$rsta."(\s*-->)?/is", '<?php ob_end_clean();?>', $template);
    //stop 语句
    $template = preg_replace("/(<!--\s*)?".$lsta."\s*(stop)\s*".$rsta."(\s*-->)?/is", '<?php exit; ?>', $template);
    //换行
    $template = preg_replace('/\?\>[\s\v\f\r\n]*\<\?php/is', ' ', $template);

    //还原 pre 里面的内容
    $template = str_replace($pre_new[0], $pre_old[3], $template);
    //附加处理
    $template = "<?php defined('TD_TRUE') or die(header('HTTP/1.1 404 NOT FOUND')); if(TD_DBUG)subtplcheck('".implode('|', $this->subtemplates)."', '$_G[timestamp]', '$this->tpl','$this->cate');?>$template<?php if(TD_DBUG){include_once(TD_LIB.'./debug/debug.inc.php');}?>";

    //write

    if(!file_exists($this->objpath)){
    if(!mkdir($this->objpath))
       exit('File: can not create folder '.$this->objpath);
    }
      if(@$fp = fopen($this->objfile, 'w')) {
      flock($fp, 2);
      fwrite($fp, $template);
      fclose($fp);
    } else {
      exit('File: '.$this->objfile.' can not be write!');
    }

  }


  function addquote($var) {
    return str_replace("\\\"", "\"", preg_replace("/\[([a-zA-Z0-9_\-\.\x7f-\xff]+)\]/s", "['\\1']", $var));
  }

  function striptagquotes($expr) {
    $expr = preg_replace("/\<\?php echo(\\\$.+?)\?\>/s", "\\1", $expr);
    $expr = str_replace("\\\"", "\"", preg_replace("/\[\'([a-zA-Z0-9_\-\.\x7f-\xff]+)\'\]/s", "[\\1]", $expr));
    return $expr;
  }

  function stripvtags($expr, $statement='') {
    $expr = str_replace("\\\"", "\"", preg_replace("/\<\?php (print_r|echo|out)\((.+?)\);\s*\?\>/s", "\\2", $expr));
    return $expr;
  }


function readtemplate($name,$parent) {
    global $_G, $_C;
    $file = $this->tplpath.$name.$_C['tpl_ex'];

    //检查是否循环调用，避免程序失去响应
    if(in_array($name,$this->subtemplates)){
    if(TD_DBUG) showdebuginfo('the <font color="#0000FF">{include '.$name.'} </font>tag in <font color="#0000FF">'.$this->tplpath.$parent.$_C['tpl_ex'].'</font>  file gets into an endless loop!');
    return;
  }
    $this->subtemplates[] = $name;
    			if(!file_exists($file)) {
    if(TD_DBUG) showdebuginfo('<font color="#0000FF">'.$file.'</font> Not found or have no access!');
			return ;
			}
    if(function_exists('file_get_contents')) {
      @$content = file_get_contents($file);
    } else {
      if(@$fp = fopen($file, 'r')) {
        @$content = fread($fp, filesize($file));
        @fclose($fp);
      }
    }
    $parent=$name;
    $lsta = quotemeta($this->lsta);
    $rsta = quotemeta($this->rsta);
    $content = preg_replace("/".$lsta."\s*include\s+([a-z0-9_\/]+)\s*".$rsta."/ie", "Template::readtemplate('\\1',$parent)", $content);
    return $content;
  }

function tag_set($matches){
	  //out($matches);
	  //preg_quote
    $lsta = preg_quote($this->lsta);
    $rsta = preg_quote($this->rsta);
    $lvar = preg_quote($this->lvar);
    $rvar = preg_quote($this->rvar);
    $var_regexp = '([a-zA-Z_\?\x7f-\xff][a-zA-Z0-9\?_\x7f-\xff]*(\.[a-zA-Z0-9_\?\x7f-\xff]+)*)';
    $var_modifier_regexp = '(((\|\s*('.implode('|',array_keys($this->varfuns)).'|\?))(.*?))*)';
    if(strtolower($matches[4])=='c'){
			return '<?php setcookie(\''.$matches[5].'\', '.preg_replace_callback("/(<!--\s*)?".$lvar."\s*(([sSuUlLvVgGpPcC\?])\s*\:)?\s*".$var_regexp.$var_modifier_regexp."\s*".$rvar."(\s*-->)?/s", array( Template, 'tag_var'), $matches[7]).', time()+3600);?>';
    }else{
    	return '<?php '.preg_replace_callback("/(<!--\s*)?".$lvar."\s*(([sSuUlLvVgGpPcC\?])\s*\:)?\s*".$var_regexp.$var_modifier_regexp."\s*".$rvar."(\s*-->)?/s", array( Template, 'tag_var'), $matches[2]).' ;?>';
    	}

	}

function tag_var_out($matches) {
  //变量类型
  $vartypename = strtolower($matches[3]);
  //变量名
  $varstr = $matches[4];
  //修正字符串
  $funstr = $matches[6];
  return '<?php out('.$this->_var($vartypename,$varstr,$funstr).');?>';
}

function tag_var($matches) {
  //变量类型
  $vartypename = strtolower($matches[3]);
  //变量名
  $varstr = $matches[4];
  //修正字符串
  $funstr = $matches[6];
  return $this->_var($vartypename,$varstr,$funstr);

}

function _var($vartypename,$varstr,$funstr) {
  if (empty($vartypename)) {
    $vartypename = 'v';
  }
  //特殊符号(?)代表调试输出
   elseif ($vartypename == '?') {
    return array_keys($this->vartype);
  }
  $vartype = $this->vartype[$vartypename];

  $vararr = explode('.', trim($varstr, '.'));
  $var = '';
  foreach($vararr as $varname) {
    if (!empty($varname))
    //特殊符号(?)代表调试输出
    if ($varname == '?') {
      return 'arraykeys('.$vartype.$var.')';
    } elseif ($varname == '??') {
      return $vartype.$var;
    }
    $var .= '[\''.$varname.'\']';
  }
  //组装变量
  $var = $vartype.$var;
  //处理修正函数字符串
  if($funstr){
  preg_match_all('/\|\s*('.implode('|',array_keys($this->varfuns)).'|\?)(\:(([\d\.]+|(\'\s*.*?\s*\'|\"\s*.*?\s*\"))(\s*,\s*([\d\.]+|(\'\s*.*?\s*\'|\"\s*.*?\s*\")))*))?/',$funstr,$fmatches);
  //函数数组，$fmatches[1]
	foreach($fmatches[1] as $key => $fun){
    if ($fun == '?') {
      return array_keys($this->varfuns);
    }
    //参数数组，$matches[3]
    if(empty($fmatches[3][$key])){
			$var = $this->varfuns[$fun].'('.$var.')';
    	}else{
    		if ($fun == 'replace') {
					$var = $this->varfuns[$fun].'('.$fmatches[3][$key].','.$var.')';
				}else{
					$var = $this->varfuns[$fun].'('.$var.','.$fmatches[3][$key].')';
				}
		}
	}
}
  return $var;
}

function tag_loop($matches) {
  $loop = '';
  $loop_index = '';
  //待循环的数组
  $loopvalue = Template::stripvtags($matches[3]);
  //循环赋值变量
  $var = '$_PAGEVAR[\''.$matches[2].'\']';
  $loopvar = '$'.$matches[2];
  $loop_before = $loopvar."_num =0;\n";
  $loop_before .= $loopvar."_first =true;\n";
  $loop_before .= $loopvar."_last =false;\n";
  $loop_before .= $loopvar."_total =count(".$loopvalue.");\n";

  $loop_after = $loopvar."_num ++;\n";
  $loop_after .= 'if('.$loopvar."_num !=1)".$loopvar."_first =false;\n";
  $loop_after .= 'if('.$loopvar."_num ==".$loopvar."_total )".$loopvar."_last =true;\n";

  $loop = $loop_before.'if(is_array('.$loopvalue.')) { foreach('.$loopvalue.' as '.$var.") { \n".$loop_after;
  $loop .= $var."['_first']=".$loopvar."_first;\n";
  $loop .= $var."['_last']=".$loopvar."_last;\n";
  $loop .= $var."['_num']=".$loopvar."_num;\n";
  $loop .= $var."['_total']=".$loopvar."_total;\n";

  return "<?php\n".$loop.'?>';
}

function tag_avatar($matches){
    //out($matches);
    //类型
    $type = $matches[1];
    //用户id,变量或者数字,如果为空，则默认当前登录用户。
    $id = $matches[4];
    //大小
    $size = $matches[2];
    //后缀
    $ex = $matches[5];
$uid = '';
if(empty($id)){
$uid = '$_G[\'uid\']';
	}
elseif(is_numeric($id)){
$uid = $id;
}else{
 //变量名
  $id = trim($id,$this->lvar.$this->rvar);
  $vararr = explode('.', trim($id, '.'));
  $var = '';
  foreach($vararr as $varname) {
    if (!empty($varname))
    //特殊符号(?)代表调试输出
    if ($varname == '?') {
      return '<?php out(arraykeys($_PAGEVAR'.$var.')); ?>';
    } elseif ($varname == '??') {
      return '<?php out($_PAGEVAR'.$var.'); ?>';
    }
    $var .= '[\''.$varname.'\']';
  }
$uid = '$_PAGEVAR'.$var;

}
if($type == ''){
	$useravatar = $this->tplrelativeuri.'_AVATAR_/'.$size.'.'.$ex;
	}

return('<?php echo getavatar('.$uid.', \''.strtolower($size).'\', \''.$useravatar.'\');?>');

	}


function tag_block($matches){
//out($matches);
$block = '';
$sql = '';
$sqlwhere = '';
//表名
$table = strtolower($matches[2]);
//表名合理
if(in_array($table,$this->tables)){
	global $_G;
	$sql = "SELECT * FROM ".tname($table);
	$countsql = "SELECT COUNT(*) FROM ".tname($table);
	//获取该表的字段
	$columns = $_G['db']->fetch_fields(tname($table));
	//参数
	$paramstr = $matches[3];
  $paramold = $param = array();
  $paramold = $this->_param($paramstr);
  //字段名,去除PHP标签，支持变量
  $usevar = FALSE;
  foreach($paramold as $k => $v){

  	if($k=='_count'){
  	 $param[$k] = $this->stripvtags($v);
  	}else{
  		$param[$k] = str_replace("\\\"", "\"", preg_replace("/\<\?php (print_r|echo|out)\((.+?)\);\s*\?\>/s", "\".addslashes(\\2).\"", $v));
  		}

    //如果存在参数值是变量的情况。
		if($param[$k]!=$v)$usevar = TRUE;
  	}

	$_name = $_cache = $_page = $_count = $order = '';
	foreach($param as $k => $v){
	//参数为系统字段
	if(in_array($k,array('_name','_page','_cache','_count','order'))){
		$$k = $param[$k];
	//参数为表中的字段
	}elseif(in_array($k,$columns['Field'])){
    	$paramvalue = "'".addslashes($param[$k])."'";
    	$paramname = $k;
    	$sqlwhere .= $sqlwhere ? ' AND '.$paramname.'='.$paramvalue : $paramname.'='.$paramvalue;
			//无效的参数(invalid parameter)
			}else{
  			if(TD_DBUG) showdebuginfo('invalid parameter <font color="#0000FF">'.$k.'</font> in <font color="#0000FF">block:'.$table.'</font> tag !',TRUE);
			}
	}

	if(!$_name){
		if(TD_DBUG) showdebuginfo('the <font color="#0000FF">_name</font> parameter is required in <font color="#0000FF">block:'.$table.'</font> tag !');
		return ;
  }

  if($usevar){
   //如果参数值使用了变量，则自动关闭缓存
   if(isset($param['_cache'])){
   	if(TD_DBUG) showdebuginfo('parameter <font color="#0000FF">_cache</font> is disabled while using variable in <font color="#0000FF">block:'.$table.'</font> tag !',TRUE);
   	}
   $_cache = 0;
  //d($param);
	if($param['_name']!=$paramold['_name']||$param['_page']!=$paramold['_page']||$param['_cache']!=$paramold['_cache']){
		if(TD_DBUG) showdebuginfo('Constant expression required for <font color="#0000FF">_name _page _cache</font> in <font color="#0000FF">block:'.$table.'</font> tag !');
		return ;
  }

  }

	$sqlwhere = $sqlwhere ? ' WHERE '.$sqlwhere : '';
	$order = $order ? ' ORDER BY '.$order:'';
	$sql .= $sqlwhere.$order;
	$countsql .= $sqlwhere.$order;
  ////////////////
  $this->tagindex++;
  $pre = '$block_'.$this->tagindex.'_';
  ///////////////
  $block .= $pre.'blocklist = array();'."\n";
  $block .= $pre.'counts = $_G[\'db\']->result($_G[\'db\']->query("'.$countsql.'"), 0);'."\n";
	$block .= 'if('.$pre.'counts){'."\n";
	$block .= is_numeric($_count) ? $pre.'pagesize = '.intval($_count).';': $pre.'pagesize = is_numeric('.$_count.') ? intval('.$_count.'):$_PN_SET[\'pagesize\'];'."\n";
  if($_page){
	$block .= $pre.'curpage = empty($_GET[\''.$_page.'\'])||($_GET[\''.$_page.'\']<1)?1:intval($_GET[\''.$_page.'\']);'."\n";
	$block .= $pre.'totalpages = @ceil('.$pre.'counts / '.$pre.'pagesize);'."\n";
	$block .= $pre.'curpage = '.$pre.'curpage > '.$pre.'totalpages ? '.$pre.'totalpages:'.$pre.'curpage;'."\n";
	$block .= $pre.'start = ('.$pre.'curpage-1)*'.$pre.'pagesize;'."\n";
	$block .= $pre.'theurl = url_wrap($_GET[\'module\'],$_GET[\'do\'],$_GET[\'id\'],$_GET[\'action\'],\'\',FALSE);'."\n";
  $block .= $pre.'pn = get_pagination('.$pre.'counts,'.$pre.'curpage,'.$pre.'theurl,\''.$_page.'\','.$pre.'pagesize);'."\n";
  $block .= 'assign(\''.$_page.'\',&'.$pre.'pn);'."\n";
	}else{
	$block .= $pre.'start = 0;'."\n";
	}
	$block .= $pre.'query = $_G[\'db\']->query(" '.$sql.' LIMIT '.$pre.'start,'.$pre.'pagesize");'."\n";
	$block .= 'while ('.$pre.'value = $_G[\'db\']->fetch_array('.$pre.'query)) {'."\n";
	$block .= 'if(!'.$pre.'value[\'url\']){'."\n";
	$block .= $pre.'warpid = ('.$pre.'value[\'alias\']&&$_C[\'url_usealias\'])? '.$pre.'value[\'alias\']:'.$pre.'value[\'id\'];'."\n";
	$block .= $pre.'value[\'url\']= url_wrap(\''.$table.'\',\'view\','.$pre.'warpid,\'\',\'\',TRUE);}'."\n";
	$block .= $pre.'blocklist[] = '.$pre.'value;}}'."\n";
  $block .= 'assign(\''.$_name.'\',&'.$pre.'blocklist);'."\n";
  ///////////////
  if(strtolower($_cache)=='true' || $_cache=='1'){
  	$blockcache = '';
  	$limitend = is_numeric($_count) ? intval($_count):'{$_PN_SET[\'pagesize\']}';
		$sql = $sql.' LIMIT 0,'.$limitend;
  if($_page){
  	    $blockcache .= $pre.'curpage = empty($_GET[\''.$_page.'\'])||($_GET[\''.$_page.'\']<1)?1:intval($_GET[\''.$_page.'\']);'."\n";
				$blockcache .= 'if('.$pre.'curpage==1){'."\n";
  			$blockcache .= 'if(!@include_once(TD_ROOT.\'./cache/block/cache_'.$this->tpl.'.php\')||!isset($_CACHE[\''.md5($sql).'\'])) {include_once(TD_LIB.\'./cache/cache.func.php\');sql_cache(\''.$this->tpl.'\',\''.$table.'\',"'.$sql.'");}'."\n";
	      $blockcache .= 'assign(\''.$_name.'\',&$_CACHE[\''.md5($sql).'\']);'."\n";
	      $blockcache .= $pre.'counts = $_G[\'db\']->result($_G[\'db\']->query("'.$countsql.'"), 0);'."\n";
	      $blockcache .= $pre.'theurl = url_wrap($_GET[\'module\'],$_GET[\'do\'],$_GET[\'id\'],$_GET[\'action\'],\'\',FALSE);'."\n";
	      $blockcache .= is_numeric($_count) ? $pre.'pagesize = '.intval($_count).';': $pre.'pagesize = is_numeric('.$_count.') ? intval('.$_count.'):$_PN_SET[\'pagesize\'];'."\n";
	      $blockcache .= $pre.'pn = get_pagination('.$pre.'counts,1,'.$pre.'theurl,\''.$_page.'\','.$pre.'pagesize);'."\n";
	      $blockcache .= 'assign(\''.$_page.'\',&'.$pre.'pn);'."\n";
	      $blockcache .= '}else{'."\n";
	      $blockcache .= $block.'}'."\n";
	      return '<?php '.$blockcache.' ?>';
  	}else{//启动缓存，且没有分页，则所有的数据就一个列表，直接编译为读取缓存的代码。
  			$blockcache .= 'if(!@include_once(TD_ROOT.\'./cache/block/cache_'.$this->tpl.'.php\')||!isset($_CACHE[\''.md5($sql).'\'])) {include_once(TD_LIB.\'./cache/cache.func.php\');sql_cache(\''.$this->tpl.'\',\''.$table.'\',"'.$sql.'");}'."\n";
	      $blockcache .= 'assign(\''.$_name.'\',&$_CACHE[\''.md5($sql).'\']);'."\n";
  		  return '<?php '.$blockcache.' ?>';
  		}

  }else{
  return '<?php '.$block.' ?>';
  }
  ////////////////
}else{
if(TD_DBUG) showdebuginfo(':the block name <font color="#0000FF">'.$table.'</font> is not interpretable !');
return ;
	}



}


function tag_item($matches){
//表名
$table = strtolower($matches[2]);
//表名合理
if(in_array($table,$this->tables)){
	global $_G;
	//获取该表的字段
	$columns = $_G['db']->fetch_fields(tname($table));
	//参数
	$paramstr = $matches[3];
  $paramold = $param = array();
  $paramold = $this->_param($paramstr);
  //参数中使用变量
  $usevar = FALSE;
  //字段名,去除PHP标签，支持变量
  foreach($paramold as $k => $v){
  	  	if($k=='_count'){
  	 $param[$k] = $this->stripvtags($v);
  	}else{
  		$param[$k] = str_replace("\\\"", "\"", preg_replace("/\<\?php (print_r|echo|out)\((.+?)\);\s*\?\>/s", "\".addslashes(\\2).\"", $v));
  		}
  	//如果存在参数值是变量的情况。
		if($param[$k]!=$v)$usevar = TRUE;
  	}
	$_name = $_cache = $order = '';
	$sql = '';
  $sqlwhere = '';
	foreach($param as $k => $v){
	//参数为系统字段
	if(in_array($k,array('_name','_cache','order'))){
		$$k = $param[$k];
	//参数为表中的字段
	}elseif(in_array($k,$columns['Field'])){
    	$paramvalue = "'".$param[$k]."'";
    	$paramname = addslashes($k);
    	$sqlwhere .= $sqlwhere ? ' AND '.$paramname.'='.$paramvalue : $paramname.'='.$paramvalue;
			//无效的参数(invalid parameter)
			}else{
  			if(TD_DBUG) showdebuginfo('invalid parameter <font color="#0000FF">'.$k.'</font> in <font color="#0000FF">item:'.$table.'</font> tag !',TRUE);
			}
	}
	if(!$_name){
		if(TD_DBUG) showdebuginfo('the <font color="#0000FF">_name</font> parameter is required in <font color="#0000FF">item:'.$table.'</font> tag !');
		return ;
  }

  if($usevar){
   //如果参数值使用了变量，则自动关闭缓存
   if(isset($param['_cache'])){
   	if(TD_DBUG) showdebuginfo('parameter <font color="#0000FF">_cache</font> is disabled while using variable in <font color="#0000FF">item:'.$table.'</font> tag !',TRUE);
   	}
   $_cache = 0;
	if($param['_name']!=$paramold['_name']||$param['_cache']!=$paramold['_cache']){
		if(TD_DBUG) showdebuginfo('Constant expression required for <font color="#0000FF">_name _page _cache</font> in <font color="#0000FF">block:'.$table.'</font> tag !');
		return ;
  }
  }

  $sqlwhere = $sqlwhere ? ' WHERE '.$sqlwhere : '';
	$order = $order ? ' ORDER BY '.$order:'';
	$sql = "SELECT * FROM ".tname($table).$sqlwhere.$order.' LIMIT 0,1';
  $this->tagindex++;
  $pre = '$item_'.$this->tagindex.'_';
  if(strtolower($_cache)=='true' || $_cache=='1'){
	  $item .= 'if(!@include_once(TD_ROOT.\'./cache/block/cache_'.$this->tpl.'.php\')||!isset($_CACHE[\''.md5($sql).'\'])) {include_once(TD_LIB.\'./cache/cache.func.php\');sql_cache(\''.$this->tpl.'\',\''.$table.'\',"'.$sql.'",1);}'."\n";
		$item .= 'assign(\''.$_name.'\',&$_CACHE[\''.md5($sql).'\']);'."\n";
  	}else{
 	 	$item .= $pre.'value = array();'."\n";
 	 	$item .= $pre.'query = $_G[\'db\']->query(" '.$sql.' ");'."\n";
  	$item .= $pre.'value = $_G[\'db\']->fetch_array('.$pre.'query);'."\n";
  	$item .= 'assign(\''.$_name.'\',&'.$pre.'value);'."\n";
  	}
  return '<?php '.$item.' ?>';



}//end 表合理判断


}//end tagfun

//url_wrap($module,$do,$id,$action,$with_ex)
function tag_url($matches){
//$matches[2] 参数列表,如：admin,article,1,edit
$pam = explode(',',$matches[2]);
$syspam = $userpam = array();
for($i=0;$i< count($pam);$i++ ){
	if($i < 4){
		$syspam[$i] = "'".$pam[$i]."'";
	}else{
		$userpam[$pam[$i]] = $pam[++$i];
	}
}
$pamstr = implode(',',$syspam).','.var_export($userpam,TRUE);
$pamstr = str_replace("\'", "'", preg_replace("/\'\<\?php (print_r|echo|out)\((.+?)\);\s*\?\>\'/s", "\\2", $pamstr));
	return '<?php echo url_wrap('.$pamstr.',1 );?>';
	}


//输入参数字符串，返回参数数组，键=参数名，值=参数值。
function _param($paramstr){
	$param = $paramarr = array();
	preg_match_all('/([a-zA-Z0-9_]+)\s*\=\s*\"\s*(.*?)\s*\"/',$paramstr,$paramarr);
  //$paramarr[1]参数名数组，$paramarr[2]参数值数组
  //根据参数名和参数值生成参数数组
	foreach($paramarr[2] as $k => $v){
		$param[$paramarr[1][$k]] = $v;
		}
  return $param;
}





}//end class
?>